package io.nutz.irtu.gpsserver.bean;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.List;

import org.nutz.dao.entity.annotation.ColDefine;
import org.nutz.dao.entity.annotation.Index;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.entity.annotation.TableIndexes;
import org.nutz.dao.interceptor.annotation.PrevInsert;

import ch.hsr.geohash.GeoHash;
import io.nutz.irtu.gpsserver.util.WoozTools;

@Table("dev_loc")
@TableIndexes({@Index(fields= {"imei", "devtime"}, unique=false)})
public class DevLocMsg extends AbstractDevMsg {
    @PrevInsert(uu32=true)
    protected String id;

    // isFix, os.time(), lng, lat, altitude, azimuth, speed, sateCno, sateCnt
    protected boolean fixed;
    protected long devtime;
    protected double lng;
    protected double lat;
    protected int altitude;
    protected int azimuth;
    protected int speed;
    protected int sateCno;
    protected int sateCnt;
    @ColDefine(width=10)
    protected String geohash;
    protected double gcj02_lng;
    protected double gcj02_lat;
    
    public static final DevLocMsg from(List<Object> list) {
        Object[] params = list.toArray(new Object[list.size()]);
        DevLocMsg msg = new DevLocMsg();
        msg.fixed = ((Boolean)params[0]).booleanValue();
        msg.devtime = ((Number)params[1]).longValue();
        msg.lng = ((Number)params[2]).doubleValue() / 10000000;
        msg.lat = ((Number)params[3]).doubleValue() / 10000000;
        msg.altitude = ((Number)params[4]).intValue();
        msg.azimuth = ((Number)params[5]).intValue();
        msg.speed = ((Number)params[6]).intValue();
        msg.sateCno = ((Number)params[7]).intValue();
        msg.sateCnt = ((Number)params[8]).intValue();
        msg.srvtime = System.currentTimeMillis();
        _loc_post(msg);
        return msg;
    }
    public static DevLocMsg from(byte[] buf) {
        try {
            DevLocMsg msg = new DevLocMsg();
            DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf));
            dis.readUnsignedByte(); // skip header
            msg.fixed = dis.readBoolean();
            msg.devtime = dis.readUnsignedShort() * 256*256 + dis.readUnsignedShort();
            msg.lng = (dis.readUnsignedShort() * 256*256 + dis.readUnsignedShort()) / 10000000.0;
            msg.lat = (dis.readUnsignedShort() * 256*256 + dis.readUnsignedShort()) / 10000000.0;
            msg.altitude = dis.readUnsignedShort();
            msg.azimuth = dis.readUnsignedShort();
            msg.speed = dis.readUnsignedByte();
            msg.sateCno = dis.readUnsignedByte();
            msg.sateCnt = dis.readUnsignedByte();
            msg.srvtime = System.currentTimeMillis();
            _loc_post(msg);
            return msg;
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    protected static void _loc_post(DevLocMsg msg) {
        if (msg.lng != 0 && msg.lat != 0) {
            double[] tmp = WoozTools.wgs84togcj02(msg.lng, msg.lat);
            msg.gcj02_lng = tmp[0];
            msg.gcj02_lat = tmp[1];
            msg.geohash = GeoHash.geoHashStringWithCharacterPrecision(msg.gcj02_lat, msg.gcj02_lng, 8);
        }
    }
    
    public boolean isFixed() {
        return fixed;
    }
    public void setFixed(boolean fixed) {
        this.fixed = fixed;
    }
    public long getDevtime() {
        return devtime;
    }
    public void setDevtime(long devtime) {
        this.devtime = devtime;
    }
    public double getLng() {
        return lng;
    }
    public void setLng(double lng) {
        this.lng = lng;
    }
    public double getLat() {
        return lat;
    }
    public void setLat(double lat) {
        this.lat = lat;
    }
    public int getAltitude() {
        return altitude;
    }
    public void setAltitude(int altitude) {
        this.altitude = altitude;
    }
    public int getAzimuth() {
        return azimuth;
    }
    public void setAzimuth(int azimuth) {
        this.azimuth = azimuth;
    }
    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    public int getSateCno() {
        return sateCno;
    }
    public void setSateCno(int sateCno) {
        this.sateCno = sateCno;
    }
    public int getSateCnt() {
        return sateCnt;
    }
    public void setSateCnt(int sateCnt) {
        this.sateCnt = sateCnt;
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
}
